
#include "copyright.h"
#include "system.h"
#include "synch.h"
#include <ctime>

int THEATER_TESTS = -9999;



bool seats[5][5];

Thread *customerThread[100];
int custsSeated=0;
Thread *managerThread;

bool customerTheater = false;
bool takingTickets = true;
int ticketsTaken;
int seatedPeople=0;
Lock *lobbyLock = new Lock("Lobby Lock"); /*LockCreate("Lobby Lock", 10);*/
Condition *lobbyCV = new Condition("The Lobby Is A Boring Place"); /*CVCreate("The Lobby Is A Boring Place", 27);*/

int customersServed;
int ticketClerks;
int foodClerks;
int ticketTakers;
int customers;

bool movieStarted=0;

enum TechStateEnum{} techState;

int numberOfCustomers=0;

Lock *seatsFreeLock;
int seatsFree[5];

const int BREAK_LENGTH=200;

const int MAX_TAKER = 3;

Lock *theaterLock = new Lock("Theater Lock"); /*LockCreate("Theater Lock", 12);*/
Condition *theaterCV = new Condition("Theater CV"); /*CVCreate("Theater CV", 10);*/


#include "ticketclerk.cc"
#include "foodclerk.cc"
#include "tickettaker.cc"
#include "tech.cc"
#include "customer.cc"
#include "manager.cc"


void SetupTheater()
{
		while(true)
		{
			char choice;
			printf("Would you like to make your own theater? y/n \n");
			choice=getchar();
			if(choice=='y')
			{
				customerTheater = true;
				break;	
			}
			else if(choice=='n')
				break;
		}
		char c;
		while(c = getchar() != '\n' && c != EOF);

		srand(time(NULL));
		for(int i = 0; i<5; i++)
		{
			for(int j = 0; j<5; j++)
			{
				seats[i][j]=true;
			}

			seatsFree[i] = 5;
		}
		
		seatsFreeLock = new Lock("seats free line lock"); /*LockCreate("seats free line lock", 20);*/
		ticketClerkLineLock = new Lock("ticket clerk line lock"); /*LockCreate("ticket clerk line lock", 22);*/
		int numberOfClerks;
		if(customerTheater)
		{
			while(true)
			{
				printf("How Many Ticket Clerks?\n");
				scanf("%d",&numberOfClerks);
				printf("numberOfClerks is %i\n", numberOfClerks);
				if(numberOfClerks<6&&numberOfClerks>0)
				{
					break;
				}
			}
		}
		else
			numberOfClerks = (rand()%MAX_CLERK)+1;
		ticketClerks=numberOfClerks;
		for(int i = numberOfClerks; i < 5; i++)
		{
			ticketClerkThreads[i] = NULL;
			ticketClerkConditionVariables[i] = NULL;
			ticketClerkLineConditionVariables[i] = NULL;
			ticketClerkLocks[i] =NULL;
			ticketClerkLineCount[i] = 999999;
			ticketEarnings[i]=0;
			ticketClerkState[i] = no_clerk;
		}

		for(int i = numberOfClerks-1; i >= 0; i--)
		{
			ticketClerkThreads[i] = new Thread("Ticket Clerk ");
			ticketClerkConditionVariables[i] = new Condition("ticketClerkCondition"); /*CVCreate("ticketClerkCondition", 20);*/
			ticketClerkLineConditionVariables[i] = new Condition("ticketClerkLineCondition"); /*CVCreate("ticketClerkLineCondition", 24);*/
			ticketClerkLocks[i] = new Lock("Ticket Clerk Lock"); /*LockCreate("Ticket Clerk Lock", 17);*/
			ticketClerkLineCount[i] = 0;
			ticketEarnings[i]=0;
			ticketClerkState[i] = available;
			ticketClerkThreads[i]->Fork((VoidFunctionPtr)TicketClerk,i);
		}
		
		foodClerkLineLock = new Lock("Food Clerk Line Lock");
		/*foodClerkLineLock = LockCreate("Food Clerk Line Lock", 20);*/
		if(customerTheater)
		{
			while(true)
			{
				printf("How Many Food Clerks?\n");
				scanf("%d",&numberOfClerks);
				printf("numberOfClerks is %i\n", numberOfClerks);
				if(numberOfClerks<6&&numberOfClerks>0)
				{
					break;
				}
			}
		}
		else
			numberOfClerks = (rand()%MAX_CLERK)+1;
		foodClerks=numberOfClerks;
		for(int i = numberOfClerks; i<5; i++)
		{
			foodClerkThreads[i] = NULL;
			foodClerkConditionVariables[i] = NULL;
			foodClerkLineConditionVariables[i] = NULL;
			foodClerkLocks[i] = NULL;
			foodClerkLineCount[i] = 9999;
			foodEarnings[i] = 0;
			foodClerkStates[i] = no_clerk;
		}
		
		for(int i = numberOfClerks-1; i >= 0; i--)
		{
			foodClerkThreads[i] = new Thread("Food Clerk Thread ");
			foodClerkConditionVariables[i] = new Condition("Food Clerk Condition"); /*CVCreate("Food Clerk Condition", 20);*/
			foodClerkLineConditionVariables[i] = new Condition("Food Clerk Line Condition"); /*CVCreate("Food Clerk Line Condition", 25);*/
			foodClerkLocks[i] = new Lock("Food Clerk Lock"); /*LockCreate("Food Clerk Lock", 15);*/
			foodClerkLineCount[i] = 0;
			foodEarnings[i] = 0;
			foodClerkStates[i] = available;
			foodClerkThreads[i]->Fork((VoidFunctionPtr)FoodClerk,i);
		}
		
		ticketTakerLineLock = new Lock("Ticket Taker Line Lock"); /*LockCreate("Ticket Taker Line Lock", 22);*/
		takingTickets = true;
		ticketsTaken = 0;
		totalTicketLock = new Lock("Total Ticket Lock"); /*LockCreate("Total Ticket Lock", 17);*/
		takingTicketsLock = new Lock("Taking Tickets Lock"); /*LockCreate("Taking Tickets Lock", 19);*/
		if(customerTheater)
		{
			while(true)
			{
				printf("How Many Ticket Takers?\n");
				scanf("%d",&numberOfClerks);
				printf("numberOfClerks is %i\n", numberOfClerks);
				if(numberOfClerks<4&&numberOfClerks>0)
				{
					break;
				}
			}
		}
		else
			numberOfClerks = (rand()%MAX_TAKER)+1;
		ticketTakers = numberOfClerks;
		for(int i = numberOfClerks; i<5; i++)
		{
			ticketTakerThreads[i] = NULL;
			ticketTakerConditionVariables[i] = NULL;
			ticketTakerLineConditionVariables[i] = NULL;
			ticketTakerLocks[i] = NULL;
			ticketTakerLineCount[i] = 9999;
			ticketTakerStates[i] = no_clerk;
		}
		
		for(int i = numberOfClerks-1; i >= 0; i--)
		{
			ticketTakerThreads[i] = new Thread("Ticket Taker Thread");
			ticketTakerConditionVariables[i] = new Condition("Ticket Taker Condition"); /*CVCreate("Ticket Taker Condition", 22);*/
			ticketTakerLineConditionVariables[i] = new Condition("Ticket Taker Line Condition"); /*CVCreate("Ticket Taker Line Condition", 27);*/
			ticketTakerLocks[i] = new Lock("Ticket Taker Lock"); /*LockCreate("Ticket Taker Lock", 17);*/
			ticketTakerLineCount[i] = 0;
			ticketTakerStates[i] = available;
			ticketTakerThreads[i]->Fork((VoidFunctionPtr)TicketTaker,i);
			
		}
			
		techMovieVariable = new Condition("Tech Movie Condition Variable"); /*CVCreate("Tech Movie Condition Variable", 29);*/
		techManagerVariable = new Condition("Tech Manager Condition Variable"); /*CVCreate("Tech Manager Condition Variable", 31);*/
		techLock = new Lock("Tech Lock"); /*LockCreate("Tech Lock", 9);*/
		techThreads = new Thread("Tech Thread");
		techThreads->Fork((VoidFunctionPtr)Tech,0);

		startMovieConditionVariable = new Condition("Start Movie Condition"); /*CVCreate("Start Movie Condition", 21);*/
		managerClerkGoingOnBreakConditionVariable = new Condition("Manager Break Condition"); /*CVCreate("Manager Break Condition", 23);*/
		managerLock = new Lock("Manager Lock"); /*LockCreate("Manager Lock", 12);*/
		managerThread = new Thread("Manager Thread");
		managerThread->Fork((VoidFunctionPtr)Manager,0);
	

		
		customers = 0;
		if(customerTheater == false) {
			groupTotal = rand()%100 + 1;
			for(int i = 0; i<groupTotal;i++)
			{
				custDataArray[i].groupSize = rand()%5 + 1;
				customers += custDataArray[i].groupSize;
				custDataArray[i].groupNum = i;
				customerThread[i] = new Thread("Test Customer");
				customerThread[i]->Fork((VoidFunctionPtr)CustomerAgent,i);
			}
	
		} else {
			
			//ask the user for # of customer groups and # of customers
			while(true) {
				printf("How many customers would you like to make?\n");
				scanf("%d", &customers);
	
				printf("How many groups would you like to make?\n");
				scanf("%d", &groupTotal);
				
				//check if data is bad
				if(customers < groupTotal) {
					printf("Too few customers for that many groups. Try again.\n");
				}
				else if(customers > groupTotal*5) {
					printf("Too many customers for that many groups. Try again.\n");
				}
				else if(customers <= 0) {
					printf("Customers must be positive.\n");
				}
				else if(groupTotal <= 0) {
					printf("Groups must be positive.\n");
				}
				else if(groupTotal > 100) {
					printf("Cannot have more than 100 groups.\n");
				}
				else {
					//data was fine so contine
					break;
				}
			}
	
			int custPerGroup = customers / groupTotal;
			int extraCust = customers % groupTotal;
			int dumbCounterThing = 0;
	
			/*calculating customers in each group*/
			for(int i = 0; i < groupTotal; i++) {
				if(dumbCounterThing < extraCust) {
					custDataArray[i].groupSize = custPerGroup + 1;
					custDataArray[i].groupNum = i;
					dumbCounterThing++;
				} else {
					custDataArray[i].groupSize = custPerGroup;
					custDataArray[i].groupNum = i;
				}
			}

			for(int i = 0; i<groupTotal;i++)
			{
				Thread *testCustomerThread = new Thread("Customer Thread" + i);
				testCustomerThread = new Thread("Test Customer");
				//printf("THEAT_TEST %d\n"
				testCustomerThread->Fork((VoidFunctionPtr)CustomerAgent, i);
			}
			
		}
		
		theaterCV->Wait(theaterLock); /*CVWait(theaterCV, theaterLock);*/


}
